Skip to content

[pull] main from MetaMask:main#491

Merged
pull[bot] merged 17 commits into
Reality2byte:mainfrom
MetaMask:main
Jan 30, 2026
Merged

[pull] main from MetaMask:main#491
pull[bot] merged 17 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Jan 30, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

metamaskbot and others added 17 commits January 30, 2026 13:31
…25443)

## **Description**

Cherry-pick of commit 425beae (Nick's 429 rate limiting fix) to
release/7.62.2 branch.

This hotfix addresses HyperLiquid WebSocket rate limiting issues (429
errors) that occur during rapid market switching or TP/SL updates. The
fix introduces cache-first patterns to reduce API weight and avoid
hitting rate limits.

**Key changes:**
- Add optional `position` parameter to `updatePositionTPSL` to skip REST
API fetch when WebSocket data is available
- Implement `getOrFetchPrice` helper for WebSocket-first price retrieval
(0 weight vs 20 weight)
- Add atomic cache getter `getOrdersCacheIfInitialized()` to prevent
race conditions
- Add `getOrFetchFills` for cache-first fills retrieval
- Move `positionOpenedTimestamp` calculation into
`useHasExistingPosition` hook
- Add `currentPositionRef` sync in PerpsMarketDetailsView to prevent
stale closure issues

**Conflict resolution notes:**
The main branch uses `symbol` naming convention while release/7.62.2
uses `coin`. All conflicts were resolved by keeping the `coin` naming
convention while adopting the cache-first optimization patterns.

## **Changelog**

CHANGELOG entry: Fixed rate limiting issues (429 errors) when rapidly
switching markets or updating TP/SL orders

## **Related issues**

Fixes: Rate limiting issues on HyperLiquid API during rapid market
navigation

## **Manual testing steps**

```gherkin
Feature: Rate limiting prevention for Perps

  Scenario: User rapidly switches between markets
    Given user has the Perps feature enabled
    And user is viewing a market details page

    When user rapidly navigates between different markets (BTC -> ETH -> SOL -> BTC)
    Then no 429 rate limit errors should appear
    And market data should load correctly for each market

  Scenario: User updates TP/SL via stop loss prompt banner
    Given user has an open position without stop loss
    And the stop loss prompt banner is visible

    When user taps "Set Stop Loss" on the banner
    Then the stop loss should be set successfully
    And no rate limit errors should occur

  Scenario: User edits existing TP/SL on a position
    Given user has an open position with TP/SL set

    When user navigates to modify TP/SL
    And user updates the stop loss price
    Then the update should succeed without 429 errors
```

## **Screenshots/Recordings**

### **Before**

N/A - Bug fix for rate limiting, no visual changes

### **After**

N/A - Bug fix for rate limiting, no visual changes

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches perps trading/provider logic (`updatePositionTPSL`,
order/price/fill retrieval) and async UI state around stop-loss actions,
so regressions could impact TP/SL updates or stale-data handling, but
changes are bounded and add explicit fallbacks/tests.
> 
> **Overview**
> **Goal:** reduce HyperLiquid REST API weight (and 429s) during rapid
market switching and TP/SL operations by preferring WebSocket caches.
> 
> Adds cache-first primitives in `HyperLiquidSubscriptionService` (fills
cache + atomic `getOrdersCacheIfInitialized`) and `HyperLiquidProvider`
(`getOrFetchPrice`, `getOrFetchFills`), and refactors provider call
sites to use these helpers with stricter invalid-price validation and
single-DEX REST fallbacks.
> 
> Updates TP/SL flow to pass live WebSocket `position` into
`updatePositionTPSL` (avoiding a REST positions fetch), uses cached
orders to cancel existing TP/SL when available, and surfaces
partial-failure feedback in `PerpsOrderView` when order succeeds but
TP/SL update fails.
> 
> Moves `positionOpenedTimestamp` derivation into
`useHasExistingPosition` (WebSocket fills first, REST historical
fallback), and hardens `PerpsMarketDetailsView` stop-loss banner
interactions against stale closures/market switches; the banner UI
switches from a `Switch` to a "Set" button with a delayed success
checkmark + fade-out. Tests and test IDs are updated accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0edee81. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…impact) (#25147)

## **Description**

Introduces a single source of truth for build configuration
(`.github/builds.yml`) and supporting scripts so we can later migrate
from Bitrise to GitHub Actions without changing behavior today.

**What was added**
- **`.github/builds.yml`** – Defines all build variants (main-prod,
main-rc, main-test, main-e2e, main-exp, main-dev, flask-prod,
flask-test, flask-e2e, flask-dev) with env, secret mappings, code
fencing, and remote feature flag defaults.
- **Scripts** – `validate-build-config.js` (YAML validation),
`apply-build-config.js` (load config and set env),
`set-secrets-from-config.js` (map GitHub Secrets to env from config),
and `verify-build-config.js` (compare Bitrise env with builds.yml).
- **Bitrise “Phase 1.5” step** – Runs `verify-build-config.js --verbose`
in selected workflows. This step is **skippable** and runs with `||
true`, so it **never fails the build**. It only logs comparisons between
Bitrise env and builds.yml for validation.

**Important: no impact on existing workflow or Bitrise**
- Existing Bitrise env vars, remapping, and build steps are unchanged.
- No step is removed or altered except for adding the optional Phase 1.5
verification.
- The new step does not set or override env; it only reads and compares.
- `build_ios_flask_release` was removed as a thin wrapper that only
called `build_ios_flask_prod`; callers can use the prod workflow
directly.

**Reason for the change:** Prepare for Bitrise deprecation by having
build config in one place and validating parity between Bitrise and
builds.yml before any migration.

**Improvement:** Clear, version-controlled build config and optional
verification in CI without changing current Bitrise behavior or
outcomes.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

Feature: Build config and Bitrise verification

  Scenario: CI runs existing Bitrise workflows unchanged
    Given a branch with this PR merged
    When a Bitrise build runs (e2e, Android/iOS prod, etc.)
    Then all existing steps run as before
    And Phase 1.5 verification runs optionally (skippable, non-blocking)
    And the build outcome is unchanged


## **Screenshots/Recordings**
N/A – CI/config only; no UI changes.
Before
N/A
After
N/A


## **Pre-merge author checklist**
- [ ] I've followed MetaMask Contributor Docs and MetaMask Mobile Coding
Standards.
- [ ] I've completed the PR template to the best of my ability.
- [ ] I've included tests if applicable.
- [ ] I've documented my code using JSDoc format if applicable.
- [ ] I've applied the right labels on the PR (see labeling guidelines).
Not required for external contributors.

## **Pre-merge reviewer checklist**
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches CI/build configuration and removes a Bitrise workflow alias;
while the new verification step is non-blocking, misconfiguration or
missing callers could still disrupt build automation.
> 
> **Overview**
> Adds a centralized `.github/builds.yml` to define build variants (env
vars, secret mappings, code fencing, and default `remote_feature_flags`)
plus accompanying Node scripts to validate/load/export this config
(`apply-build-config.js`, `validate-build-config.js`,
`set-secrets-from-config.js`, `verify-build-config.js`).
> 
> Updates `bitrise.yml` to run an optional, skippable Phase 1.5 parity
check (`verify-build-config.js --verbose || true`) in key workflows, and
drops the redundant `build_ios_flask_release` wrapper workflow. Also
updates CODEOWNERS to protect `.github/builds.yml` and adds `js-yaml` as
a dependency.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fab10a9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…positions (#25456)

- fix(perps): potential rate limit on close positions cp-7.63.0
cp-7.64.0 cp-7.62.2 (#25438)

## **Description**

Complete the 429 rate limiting fix for position management operations.
The previous fix (commit `425beaead7`) only addressed
`updatePositionTPSL()`. This PR extends the fix to `closePosition()`,
`closePositions()`, and `updateMargin()` methods.

**Problem:** These methods were using `skipCache: true` which forced
REST API calls on every operation, leading to 429 rate limiting errors
during prolonged app usage.

**Solution:**
- Remove `skipCache: true` from `closePositions()` and `updateMargin()`
to use WebSocket cache
- For `closePosition()`, add optional `position` parameter so callers
can pass the live WebSocket position directly, avoiding the need to
fetch positions entirely
- Update `usePerpsClosePosition` hook to pass the position it already
has

## **Changelog**

CHANGELOG entry: Fixed rate limiting errors (429) when closing positions
or updating margin after prolonged app usage

## **Related issues**

Fixes: Rate limiting issues during position close/margin update
operations


## **Manual testing steps**

```gherkin
Feature: Position close without rate limiting

  Scenario: User closes position after prolonged usage
    Given user has the app open for extended period (>30 minutes)
    And user has an open perps position

    When user closes the position
    Then the position closes successfully without 429 errors

  Scenario: User updates margin after prolonged usage
    Given user has the app open for extended period (>30 minutes)
    And user has an open perps position with isolated margin

    When user adjusts the margin
    Then the margin updates successfully without 429 errors

  Scenario: User closes all positions
    Given user has multiple open perps positions

    When user uses "close all positions" feature
    Then all positions close successfully without rate limiting errors
```

## **Screenshots/Recordings**

### **Before**

N/A - Bug fix for rate limiting, no UI changes

### **After**

N/A - Bug fix for rate limiting, no UI changes

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Switches critical trading actions to rely on WebSocket-cached
positions instead of forced REST fetches, which reduces rate limiting
but risks acting on slightly stale position data during rapid state
changes.
> 
> **Overview**
> Reduces HyperLiquid REST pressure during position management by
removing `skipCache: true` position fetches in `closePositions()`,
`closePosition()`, and `updateMargin()`, so these operations prefer the
WebSocket/cache-backed `getPositions()` path.
> 
> This change is aimed at preventing 429 rate limiting during prolonged
app usage when repeatedly closing positions or adjusting margin.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a84367e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
[6f89dec](6f89dec)

---------

Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
Co-authored-by: Alejandro Garcia <alejandro.garcia@consensys.net>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?

AI agent: Be specific about what you changed and why. Include context
about the fix/feature, not generic descriptions.
-->

Some MetaMask repos (e.g. `core`) allow upcoming package changes to be
tested in Extension and/or Mobile prior to release by publishing
"preview builds".

However, using a preview build can be complicated, as care must be taken
to accurately simulate what the dependency tree of a project will look
like when a new production version is released.

To make this process easier, this commit adds a Yarn plugin. The plugin
works like this:

1. First, you must tell the plugin which preview builds you want to use
for which dependencies. You do this by adding an entry to a
`previewBuilds` section in `package.json`. For instance, to specify that
version `29.0.0-preview-3ec2a74` should be used to test non-breaking
changes to `@metamask/network-controller`, you would add:

        "previewBuilds": {
          "@metamask/network-controller": {
            "type": "non-breaking",
            "previewVersion": "29.0.0-preview-3ec2a74"
          }
        }

Similarly, you could set `type` to "breaking" to test breaking changes.

By default the plugin will assume the NPM scope of the preview build to
be `metamask-previews`, but you can change this with `previewScope`:

        "previewBuilds": {
          "@metamask/network-controller": {
            "type": "non-breaking",
            "previewScope": "my-custom-scope"
            "previewVersion": "29.0.0-preview-3ec2a74",
          }
        }

2. Next, run `yarn install`. The plugin will read the `previewBuilds`
section to determine how the dependencies you've specified should be
resolved. If the `type` of an entry is "non-breaking", all version
ranges of that dependency in the dependency tree that are
major-compatible with the corresponding entry in `dependencies` will
resolve to the preview build. If the `type` is "breaking", then only the
version range of the corresponding entry in `dependencies` will resolve
to the preview build. Finally, if a dependency is patched, the preview
build will be patched in the same way.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)

AI agent: Use format `CHANGELOG entry: [fix/feat/chore]: [User-facing
description in past tense]`.
Examples: `fix: resolved token name display issue`, `feat: added dark
mode toggle`, `chore: updated dependencies`.
For non-user-facing changes, use `CHANGELOG entry: null`.
-->

CHANGELOG entry: null

## **Related issues**

<!--
AI agent: Replace with `Fixes: #[ISSUE_NUMBER]` using the actual issue
number you're implementing.
-->

https://consensyssoftware.atlassian.net/browse/WPC-199

## **Manual testing steps**

<!--
AI agent: Write specific, contextual Gherkin steps based on what you
actually implemented.
Do NOT use generic placeholders like "my feature name". Be concrete
about the feature, scenario, and steps.
-->

- Add the following section to `package.json`:
  ```
  "previewBuilds": {
    "@metamask/network-controller": {
      "type": "breaking",
      "previewVersion": "29.0.0-preview-3ec2a74"
    }
  },
  ```
- Run `yarn install`. You should see a message at the end of the
installation steps:
  ```
[plugin-preview-builds] The following dependencies were mapped to
preview builds:
- metamask@workspace:./@metamask/network-controller@npm:^29.0.0 ->
npm:@metamask-previews/network-controller@29.0.0-preview-3ec2a74
  ```
- Run `yarn why @metamask-previews/network-controller`. You should see
only one entry:
  ```
  └─ metamask@workspace:.
└─ @metamask-previews/network-controller@npm:29.0.0-preview-3ec2a74 (via
npm:@metamask-previews/network-controller@29.0.0-preview-3ec2a74)
  ```
This proves that only the root instance of
`@metamask/network-controller` was updated to use the preview build.
- Update `previewBuilds` in `package.json` to read:
  ```
  "previewBuilds": {
    "@metamask/network-controller": {
      "type": "non-breaking",
      "previewVersion": "29.0.0-preview-3ec2a74"
    }
  },
  ```
- Run `yarn install`. You should see a message at the end of the
installation steps:
  ```
[plugin-preview-builds] The following dependencies were mapped to
preview builds:
- @metamask/network-controller@npm:^29.0.0 ->
npm:@metamask-previews/network-controller@29.0.0-preview-3ec2a74
  ```
- Run `yarn why @metamask-previews/network-controller`. You should see a
bunch of entries:
   ```
   ├─ @metamask/accounts-controller@npm:35.0.2
│ └─ @metamask-previews/network-controller@npm:29.0.0-preview-3ec2a74
(via npm:@metamask-previews/network-controller@29.0.0-preview-3ec2a74)
   │
   ├─ @metamask/accounts-controller@npm:35.0.2 [2d27a]
│ └─ @metamask-previews/network-controller@npm:29.0.0-preview-3ec2a74
(via npm:@metamask-previews/network-controller@29.0.0-preview-3ec2a74)
   │
   ├─ @metamask/accounts-controller@npm:35.0.2 [30658]
│ └─ @metamask-previews/network-controller@npm:29.0.0-preview-3ec2a74
(via npm:@metamask-previews/network-controller@29.0.0-preview-3ec2a74)
   ...
   ```
This proves that all instances of `@metamask/network-controller`
matching `^29.0.0` were updated to use the preview build.
- Now take away `previewBuilds` and re-run `yarn install`.
- Now run `yarn patch @metamask/network-controller@npm:29.0.0`. Open the
resulting patch directory and make a modification to any file. Run `yarn
patch-package <directory>` to generate the patch and update
`package.json`, then run `yarn install` to apply the patch.
- Now add the following section back to `package.json`:
  ```
  "previewBuilds": {
    "@metamask/network-controller": {
      "type": "breaking",
      "previewVersion": "29.0.0-preview-3ec2a74"
    }
  },
  ```
- Run `yarn install`. You should see a message at the end of the
installation steps:
  ```
[plugin-preview-builds] The following dependencies were mapped to
preview builds:
-
metamask@workspace:./@metamask/network-controller@patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch
->
patch:@metamask-previews/network-controller@npm%3A29.0.0-preview-3ec2a74#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch
  ```
- Run `yarn why @metamask/network-controller`. You should see a bunch of
entries:
  ```
  ├─ @metamask/accounts-controller@npm:35.0.2
│ └─
@metamask/network-controller@patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch::version=29.0.0&hash=3e054c
(via
patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch)
  │
  ├─ @metamask/accounts-controller@npm:35.0.2 [2d27a]
│ └─
@metamask/network-controller@patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch::version=29.0.0&hash=3e054c
(via
patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch)
  │
  ├─ @metamask/accounts-controller@npm:35.0.2 [30658]
│ └─
@metamask/network-controller@patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch::version=29.0.0&hash=3e054c
(via
patch:@metamask/network-controller@npm%3A29.0.0#~/.yarn/patches/@metamask-network-controller-npm-29.0.0-51af044f37.patch)
  │
  ```
  This proves that the preview build is patched.

## **Screenshots/Recordings**

(N/A)

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
AI agent: Check ALL boxes in this section (mark all as [x]).
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

<!--
AI agent: Leave ALL boxes unchecked ([ ]) - these are for reviewers to
check, not the author.
-->

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces a Yarn v4 plugin to map `@metamask/*` dependencies to
preview packages (e.g., `@metamask-previews/*`) based on a
`previewBuilds` config in `package.json`.
> 
> - New `@yarnpkg/plugin-preview-builds.cjs` implements
`validateProject`, `reduceDependency`, and `afterAllInstalled` hooks;
supports `type` (`breaking` vs `non-breaking`), optional `previewScope`,
preserves `patch:` descriptors, and logs mapped resolutions
> - Updates `.yarnrc.yml` to register the plugin and preapprove
`@metamask/*`, `@metamask-previews/*`, `@lavamoat/*`, and `@consensys/*`
for age-gate bypass
> - Adds `@yarnpkg/core` to `.depcheckrc.yml` ignores for plugin usage
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c400892. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: cryptodev-2s <109512101+cryptodev-2s@users.noreply.github.com>
## **Description**

Refactored region and state selector modals to use the new
`HeaderCenter` component from `components-temp` instead of the legacy
`BottomSheetHeader` component. This change modernizes the header
implementation by:

1. Using design system components (`Box`, `Text` from
`@metamask/design-system-react-native`) with Tailwind styling instead of
`StyleSheet`
2. Simplifying the API by using the `title` prop directly instead of
wrapping text in `<Text>` children
3. Providing a consistent header pattern across all region/state
selector modals

The following modals were updated:
- Card Onboarding RegionSelectorModal
- Ramp Deposit StateSelectorModal

## **Changelog**

CHANGELOG entry: chore: migrated region and state selector modal headers
to use HeaderCenter component

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/jira/software/c/projects/MDP/boards/2972?assignee=62afb43d33a882e2be47c36f&quickFilter=3325&selectedIssue=MDP-279

## **Manual testing steps**

```gherkin
Feature: Region and State Selector Modal Headers

  Scenario: User opens region selector in Card onboarding flow
    Given the app is launched and the user is in the Card onboarding flow
    When the user taps to select a region
    Then the region selector modal displays with a centered header title
    And the close button is visible and functional

  Scenario: User opens state selector in Deposit flow
    Given the user is in the Deposit flow and has selected a country with states
    When the user taps to select a state
    Then the state selector modal displays "Select a state" as the centered header
    And the close button dismisses the modal
```

## **Screenshots/Recordings**

### **Before**

<!-- [screenshots/recordings] -->

### **After**


https://github.com/user-attachments/assets/574830f8-8548-4a30-ab53-f4e848cb9a8e



https://github.com/user-attachments/assets/dfdaa0b4-556b-448c-a71a-206b8e03f979

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI refactor replacing `BottomSheetHeader` with `HeaderCenter`
and updating tests/snapshots; main behavioral change is wiring explicit
close button `testID`s and verifying close interactions.
> 
> **Overview**
> Migrates the Card onboarding `RegionSelectorModal` and Deposit
`StateSelectorModal` headers from legacy `BottomSheetHeader` to the new
`components-temp` `HeaderCenter`, passing titles via the `title` prop
and adding explicit close button `testID`s
(`region-selector-close-button`, `state-selector-close-button`).
> 
> Updates associated tests by removing now-unneeded header/design-system
mocks, adjusting selectors to the new close button IDs, adding a
close-button behavior test for `StateSelectorModal`, and regenerating
snapshots to reflect the new header layout/styling.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
098c8d5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR standardizes header implementations across activity-related
views by replacing various custom header patterns with the reusable
`HeaderCenter` component from the component library.

**Reason for change:**
The codebase had inconsistent header implementations across different
feature areas (Perps, Predict, Ramp, Transaction details). Each used
different approaches: custom `renderHeader()` functions, navbar options
via `getPerpsTransactionsDetailsNavbar`/`getDepositNavbarOptions`,
`BottomSheetHeader`, and `DetailsModal.Header`.

**Solution:**
Unified all header implementations to use `HeaderCenter` component,
which:
- Provides consistent styling and behavior across activity views
- Reduces code duplication by removing custom header implementations
- Simplifies navigation header management by using `headerShown: false`
with custom `HeaderCenter` rendering

**Files updated:**
- `NetworkManager` - Replaced `BottomSheetHeader` with `HeaderCenter`
- `PerpsFundingTransactionView`, `PerpsOrderTransactionView`,
`PerpsPositionTransactionView` - Replaced navbar options with
`HeaderCenter`
- `PredictActivityDetail` - Replaced custom `renderHeader()` with
`HeaderCenter`
- `Ramp/OrderDetails` - Replaced `getDepositNavbarOptions` with
`HeaderCenter`
- `TransactionElement` - Replaced `DetailsModal.Header` pattern with
`HeaderCenter`

## **Changelog**

CHANGELOG entry: chore: standardized headers across activity views to
use HeaderCenter component

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/jira/software/c/projects/MDP/boards/2972?assignee=62afb43d33a882e2be47c36f&quickFilter=3325&selectedIssue=MDP-692

## **Manual testing steps**

```gherkin
Feature: Activity View Headers

  Scenario: User views Perps transaction details
    Given user has Perps transactions in their activity
    When user taps on a Perps funding, order, or position transaction
    Then the transaction detail view displays with a centered title header and back button

  Scenario: User views Predict activity details
    Given user has Predict market activity
    When user taps on a Predict activity item
    Then the activity detail view displays with a centered title header and back button

  Scenario: User views Ramp order details
    Given user has completed a buy/sell order via Ramp
    When user navigates to the order details
    Then the order details view displays with a centered "Details" header and back button

  Scenario: User views transaction details modal
    Given user has transactions in their activity
    When user taps on a transaction to view details
    Then the transaction details modal displays with a centered title and close button

  Scenario: User opens network manager
    Given user is in the wallet
    When user opens the network manager bottom sheet
    Then the bottom sheet displays with a centered "Networks" title and close button
```

## **Screenshots/Recordings**

### **Before**

<!-- [screenshots/recordings] -->

### **After**


https://github.com/user-attachments/assets/4cce9551-2073-4b46-96a0-2b37da89629c


<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Primarily refactors UI navigation headers across several screens; risk
is mostly around regressions in back/close behavior and safe-area/layout
due to `headerShown: false` and new in-view headers.
> 
> **Overview**
> **Standardizes headers across activity-related UI** by replacing
disparate header implementations with `HeaderCenter` (NetworkManager
bottom sheet, Perps transaction detail views, Predict activity detail,
Ramp `OrderDetails`, and the transaction import-wallet modal).
> 
> Perps and Ramp screens now disable the React Navigation header via
`useLayoutEffect({ headerShown: false })` and render `HeaderCenter`
inside the view (including empty/error/loading states), with tests and
snapshots updated accordingly. Minor test/automation tweaks include
switching a Perps assertion to `toBeOnTheScreen()` and updating
`TrendingView` back navigation tap to skip visibility checks.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
226c262. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This PR updates the change log for 7.62.2. (Hotfix - no test plan
generated.)

---------

Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
# 🚀 v7.62.2 Testing & Release Quality Process

Hi Team,  
As part of our new **MetaMask Release Quality Process**, here’s a quick
overview of the key processes, testing strategies, and milestones to
ensure a smooth and high-quality deployment.

---

## 📋 Key Processes

### Testing Strategy
- **Developer Teams:**  
Conduct regression and exploratory testing for your functional areas,
including automated and manual tests for critical workflows.
- **QA Team:**  
Focus on exploratory testing across the wallet, prioritize high-impact
areas, and triage any Sentry errors found during testing.
- **Customer Success Team:**  
Validate new functionalities and provide feedback to support release
monitoring.

### GitHub Signoff
- Each team must **sign off on the Release Candidate (RC)** via GitHub
by the end of the validation timeline (**Tuesday EOD PT**).
- Ensure all tests outlined in the Testing Plan are executed, and any
identified issues are addressed.

### Issue Resolution
- **Resolve all Release Blockers** (Sev0 and Sev1) by **Tuesday EOD
PT**.
- For unresolved blockers, PRs may be reverted, or feature flags
disabled to maintain release quality and timelines.

### Cherry-Picking Criteria
- Only **critical fixes** meeting outlined criteria will be
cherry-picked.
- Developers must ensure these fixes are thoroughly reviewed, tested,
and merged by **Tuesday EOD PT**.

---

## 🗓️ Timeline and Milestones

1. **Today (Friday):** Begin Release Candidate validation.  
2. **Tuesday EOD PT:** Finalize RC with all fixes and cherry-picks.  
3. **Wednesday:** Buffer day for final checks.  
4. **Thursday:** Submit release to app stores and begin rollout to 1% of
users.
5. **Monday:** Scale deployment to 10%.  
6. **Tuesday:** Full rollout to 100%.

---

## ✅ Signoff Checklist

Each team is responsible for signing off via GitHub. Use the checkbox
below to track signoff completion:

# Team sign-off checklist
- [ ] Mobile Platform

This process is a major step forward in ensuring release stability and
quality. Let’s stay aligned and make this release a success! 🚀

Feel free to reach out if you have questions or need clarification. 

Many thanks in advance

# Reference
- Testing plan sheet -
https://docs.google.com/spreadsheets/d/1tsoodlAlyvEUpkkcNcbZ4PM9HuC9cEM80RZeoVv5OCQ/edit?gid=404070372#gid=404070372
This PR syncs the stable branch to main for version 7.65.0.

*Synchronization Process:*

- Fetches the latest changes from the remote repository
- Resets the branch to match the stable branch
- Attempts to merge changes from main into the branch
- Handles merge conflicts if they occur

*File Preservation:*

Preserves specific files from the stable branch:
  - CHANGELOG.md
  - bitrise.yml
  - android/app/build.gradle
  - ios/MetaMask.xcodeproj/project.pbxproj
  - package.json

  Indicates the next version candidate of main to 7.65.0

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Changelog-only update; no runtime code paths are modified. Risk is
limited to incorrect release notes/compare links if mis-specified.
> 
> **Overview**
> **Updates `CHANGELOG.md` to document release `7.62.2`.**
> 
> Adds a new *Fixed* section with two rate-limiting related entries, and
updates the bottom compare links so `Unreleased` now compares from
`v7.62.2` and introduces the new `7.62.2` tag link.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5902e3f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
- Move creating .env from push-eas-update.yml to build.sh
- Have eas push platform as an input so we can choose to push to all,
ios or android

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null


## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes the OTA update GitHub Actions workflow and `scripts/build.sh`
publish path, including new platform selection and altered `.env`
generation; mistakes could break release/update automation or omit
required env values.
> 
> **Overview**
> Adds a `platform` input to the `push-eas-update` workflow and passes
it through as `OTA_PUSH_PLATFORM`, allowing OTA updates to target `ios`,
`android`, or `all`.
> 
> Updates `scripts/build.sh`’s `expo-update` flow to generate `.env`
(and mirror vars into `GITHUB_ENV`) from a fixed allowlist, then publish
EAS updates **sequentially per platform** with explicit per-platform
failure reporting/propagation. Also removes the workflow’s
`EXPO_NO_LAVAMOAT` override and hardens Sentry auth token injection by
switching `sed` to a safer delimiter.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
faa3f6b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: sethkfman <seth.kaufman@consensys.net>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
Following #24313 we're
looking to centralize all tools and test resources in one place.
This PR moves spec files for `Assets`, `MultiSRP`, `Swap` and `Ramps` to
`/tests`.

Previous related PRs:
- #24988
- #24313
- #25031
- #25095
- #25167
- #25198
- #25219
- #25263


<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Test-only refactor, but it touches many specs and import paths; the
main risk is broken CI/test execution due to module resolution or path
mismatches.
> 
> **Overview**
> **Moves and rewires test specs** to run from `tests/` (notably Assets,
Ramps, and Multi-SRP-related coverage), updating imports to consistently
reference shared `e2e` page objects, tags, and `tests` fixtures/mocking
utilities.
> 
> **Centralizes SRP/account helpers** by switching various specs from
local `multisrp/utils` helpers to `tests/flows/accounts.flow.ts`
(`goToImportSrp`, `inputSrp`, `completeSrpQuiz`, etc.), and adjusts
`accounts.flow.ts` itself to import UI page objects from `e2e/pages` and
framework utilities from `tests/framework`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
95ebe1f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Jan 30, 2026
@pull pull Bot added the ⤵️ pull label Jan 30, 2026
@pull pull Bot merged commit 6d5ff23 into Reality2byte:main Jan 30, 2026
5 of 42 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants